{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mutual Information Minimization Demo\n",
    "\n",
    "In this notebook, we provide a demo for how to use estimators in `mi_estimators.py` to minimize mutual information with sample pairs under multivariate Gaussian setups."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from mi_estimators import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, we define a Gaussian sampler to generate Gaussian samples which are differentiable to the covariance coefficients. More specifically, if $\\left[\\begin{array}{c} x \\\\ y \\end{array}\\right] \\sim \\mathcal{N}\\left(\\left[\\begin{array}{c} 0\\\\0\\end{array}\\right], \\left[\\begin{array}{cc} 1 &\\rho \\\\ \\rho & 1\\end{array} \\right] \\right) $, we can parameterize the covariance matrix by $\\left[\\begin{array}{cc} 1 &\\rho \\\\ \\rho & 1\\end{array} \\right] = {SS}^T$ with $S =\\left[\\begin{array}{cc} \\cos \\theta &\\sin \\theta \\\\ \\sin \\theta & \\cos \\theta \\end{array} \\right]$. Then $\\left[\\begin{array}{c} x \\\\ y \\end{array}\\right] = Sz$ with $z$ as a standard Gaussian random vector. We aim to optimize parameter $\\theta$ to minimize the mutual information between $x$ and $y$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class GaussianSampler(nn.Module):\n",
    "    def __init__(self, dim, para_list = None):\n",
    "        super(GaussianSampler, self).__init__()\n",
    "        self.dim = dim\n",
    "        if para_list is None:\n",
    "            para_list = [0.55] * dim\n",
    "        self.p_theta_ = torch.nn.Parameter(torch.tensor(para_list, requires_grad = True))\n",
    "        \n",
    "    def get_trans_mat(self):\n",
    "        p_theta = self.p_theta_.cuda().unsqueeze(-1)\n",
    "        #p_theta = torch.softmax(p_theta, dim = 0)\n",
    "\n",
    "        trans_row1 = torch.cat((torch.sin(p_theta),torch.cos(p_theta)), dim=-1).unsqueeze(-1)\n",
    "        trans_row2 = torch.cat((torch.cos(p_theta),torch.sin(p_theta)), dim=-1).unsqueeze(-1)  #[dim, 2,1]\n",
    "        return torch.cat((trans_row1, trans_row2), dim=-1)  #[dim,2,2]\n",
    "\n",
    "    def gen_samples(self, num_sample, cuda = True):\n",
    "        noise= torch.randn(self.dim,num_sample,2).cuda()\n",
    "        trans_mat = self.get_trans_mat()\n",
    "        samples = torch.bmm(noise, trans_mat).transpose(0,1) #[dim, nsample, 2]\n",
    "        if not cuda:\n",
    "            samples = samples.cpu().detach().numpy()\n",
    "        return samples[:,:,0], samples[:,:,1] \n",
    "\n",
    "    def get_covariance(self):\n",
    "        p_theta = self.p_theta_.cuda()\n",
    "        return (2.*torch.sin(p_theta)*torch.cos(p_theta))\n",
    "\n",
    "    def get_MI(self):\n",
    "        rho = self.get_covariance()\n",
    "        return -1./2.*torch.log(1-rho**2).sum().item()\n",
    "        #return -self.dim /2.*torch.log(1-rho**2 / 2).sum().item()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "lr = 1e-4\n",
    "batch_size = 100\n",
    "num_iter = 5000\n",
    "sample_dim = 2\n",
    "hidden_size = 5\n",
    "estimator_name = \"CLUB\" "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can plot the sample pairs of variable $x$ and $y$, which has a high linear correlation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "sampler = GaussianSampler(sample_dim).cuda()\n",
    "#print(\"The corvariance of Gaussian is {}\".format(sampler.get_covariance().cpu().detach().numpy()))\n",
    "x_sample, y_sample = sampler.gen_samples(1000, cuda = False)\n",
    "plt.scatter(x_sample, y_sample)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we optimize parameter $\\theta$ to minimize the mutual information with only samples from the Gaussian distribution."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step 0, true MI value 1.5803104639053345\n",
      "step 100, true MI value 1.5069398880004883\n",
      "step 200, true MI value 1.411742091178894\n",
      "step 300, true MI value 1.3095365762710571\n",
      "step 400, true MI value 1.207322120666504\n",
      "step 500, true MI value 1.1067947149276733\n",
      "step 600, true MI value 1.0125977993011475\n",
      "step 700, true MI value 0.9223268628120422\n",
      "step 800, true MI value 0.8374634981155396\n",
      "step 900, true MI value 0.7600098848342896\n",
      "step 1000, true MI value 0.6891635656356812\n",
      "step 1100, true MI value 0.6231958270072937\n",
      "step 1200, true MI value 0.5628352165222168\n",
      "step 1300, true MI value 0.5081000924110413\n",
      "step 1400, true MI value 0.45843255519866943\n",
      "step 1500, true MI value 0.41394031047821045\n",
      "step 1600, true MI value 0.37355464696884155\n",
      "step 1700, true MI value 0.338809996843338\n",
      "step 1800, true MI value 0.30735206604003906\n",
      "step 1900, true MI value 0.27980297803878784\n",
      "step 2000, true MI value 0.25478222966194153\n",
      "step 2100, true MI value 0.2324725091457367\n",
      "step 2200, true MI value 0.21172374486923218\n",
      "step 2300, true MI value 0.19295340776443481\n",
      "step 2400, true MI value 0.1757260262966156\n",
      "step 2500, true MI value 0.15990836918354034\n",
      "step 2600, true MI value 0.14531803131103516\n",
      "step 2700, true MI value 0.13165183365345\n",
      "step 2800, true MI value 0.11914922297000885\n",
      "step 2900, true MI value 0.10756146907806396\n",
      "step 3000, true MI value 0.09695775806903839\n",
      "step 3100, true MI value 0.08720256388187408\n",
      "step 3200, true MI value 0.07807420939207077\n",
      "step 3300, true MI value 0.0697222426533699\n",
      "step 3400, true MI value 0.061964306980371475\n",
      "step 3500, true MI value 0.05496574938297272\n",
      "step 3600, true MI value 0.04849680885672569\n",
      "step 3700, true MI value 0.042551927268505096\n",
      "step 3800, true MI value 0.03717678040266037\n",
      "step 3900, true MI value 0.032239943742752075\n",
      "step 4000, true MI value 0.027783837169408798\n",
      "step 4100, true MI value 0.023765530437231064\n",
      "step 4200, true MI value 0.020208774134516716\n",
      "step 4300, true MI value 0.01700344868004322\n",
      "step 4400, true MI value 0.014230618253350258\n",
      "step 4500, true MI value 0.01179116778075695\n",
      "step 4600, true MI value 0.009627348743379116\n",
      "step 4700, true MI value 0.00773883331567049\n",
      "step 4800, true MI value 0.00611679395660758\n",
      "step 4900, true MI value 0.0047515397891402245\n"
     ]
    }
   ],
   "source": [
    "mi_estimator = eval(estimator_name)(sample_dim, sample_dim, hidden_size).cuda()\n",
    "\n",
    "sampler_optimizer = torch.optim.Adam(sampler.parameters(), lr = lr)\n",
    "mi_optimizer = torch.optim.Adam(mi_estimator.parameters(), lr = lr)\n",
    "\n",
    "mi_true_values = []\n",
    "mi_est_values = []\n",
    "min_mi = 100.\n",
    "\n",
    "for i in range(num_iter):\n",
    "    sampler.train()\n",
    "    mi_estimator.eval()\n",
    "    x_samples, y_samples = sampler.gen_samples(batch_size)\n",
    "    sampler_loss = mi_estimator(x_samples, y_samples)\n",
    "    sampler_optimizer.zero_grad()\n",
    "    sampler_loss.backward() # retain_graph=True)\n",
    "    sampler_optimizer.step()\n",
    "\n",
    "    for j in range(5):\n",
    "        mi_estimator.train()\n",
    "        x_samples, y_samples = sampler.gen_samples(batch_size)\n",
    "        mi_loss = mi_estimator.learning_loss(x_samples, y_samples)\n",
    "        mi_optimizer.zero_grad()\n",
    "        mi_loss.backward()\n",
    "        mi_optimizer.step()\n",
    "\n",
    "    mi_true_values.append(sampler.get_MI())\n",
    "    mi_est_values.append(mi_estimator(x_samples, y_samples).item())\n",
    "    if i % 100 ==0:\n",
    "        print(\"step {}, true MI value {}\".format(i, sampler.get_MI()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can plot the true MI values and the estimated MI values in each batch. The true MI value continuously decreases during the training. The estimated MI value first increases then decreases. The beginning increasing of estimated MI is because the estimator has not learned well from the samples. Then the decreasing process is the result of minimizing MI as learning loss."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(np.arange(len(mi_est_values)), mi_est_values, label=estimator_name + \" est\")\n",
    "plt.plot(np.arange(len(mi_true_values)), mi_true_values, label=\"True MI value\")\n",
    "plt.legend()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can plot samples of the optimized Gaussian sampler again, where the linear correlation between $x$ and $y$ has disappeared."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x_sample, y_sample = sampler.gen_samples(1000, cuda=False)\n",
    "plt.scatter(x_sample, y_sample)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
